package crystal.workshop;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Map;

import crystal.lib.Crystal;
import crystal.lib.StructureData;

import crystal.workshop.ui.StructureDataModel;

public class SimpleStructureData implements StructureDataModel {
	
	protected transient PropertyChangeSupport propertyChange;
	
	private final StructureData		data;
	
	/** The name given to the structure from where it generated */
	protected final String sourceName;
	
	/**
	 * Accessor for the propertyChange field.
	 */
	protected PropertyChangeSupport getPropertyChange() {
		if (propertyChange == null) {
			propertyChange = new java.beans.PropertyChangeSupport(this);
		};
		return propertyChange;
	}
	
	@Override
	public String getSourceName() {
		return sourceName;
	}
	
	/**
	 * Get the custom name for this structure.
	 * @return the custom name for this structure, if set.  Otherwise the name
	 * as set when the structure was originally loaded.
	 */
	@Override
	public String getCustomName() {
		return data.getName();
	}
	
	/**
	 * Set the custom name for this structure.
	 * @param newName the new name for the structure.
	 */
	@Override
	public void setCustomName(String newName) {
		data.setName(newName);
	}
	
	/**
	 * {@inheritDoc}
	 */
	public Crystal getCrystal() {
		return data.getCrystal();
	}
	
	
	/**
	 * {@inheritDoc}
	 */
	public Map<String, Object> getProperties() {
		return data.getProperties();
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public Object getProperty(final String name) {
		return data.getProperty(name);
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void addProperty(final String name, final Object property) {
		data.addProperty(name, property);
		firePropertyChange("structureProperty", null, name);
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public Object removeProperty(final String name) {
		final Object property = data.removeProperty(name);
		firePropertyChange("structureProperty", name, null);
		return property;
	}
	
	/**
	 * Set the crystal structure for this structure.
	 * @param newCrystal the new crystal for this structure
	 * @return the old crystal
	 */
	@Override
	public Crystal setCrystal(final Crystal newCrystal) {
		final Crystal old = data.getCrystal();
		data.setCrystal(newCrystal);
		return old;
	}
	
	/**
	 * Return the original name of this structure as set by the source from
	 * which it was loaded.
	 * @return the original name of this structure
	 */
	public String getOriginalName() {
		return data.getName();
	}
	
	/**
	 * Set the original name of this structure.  This should reflect a the
	 * value relevant to the source from which it was loaded.
	 * @param name the new name
	 * @return the old name
	 */
	public String setOriginalName(final String name) {
		final String old = data.getName();
		data.setName(name);
		return old;
	}
	
	/**
	 * Constructor to allow creation of a Structure object from its parent
	 * StructureData object
	 * @param structData the StructureData instance to create this Structure
	 * from.
	 * @param source the source that generated this structure.
	 */
	public SimpleStructureData( final String sourceName, final StructureData data) {
		this.sourceName	= sourceName;
		this.data		= data;
	}
	
	public SimpleStructureData( final String name, final Crystal crystal ) {
		this.sourceName	= name;
		this.data		= new StructureData( name, crystal );
	}
	
	public void addPropertyChangeListener(final PropertyChangeListener listener) {
		getPropertyChange().addPropertyChangeListener(listener);
	}
	
	public void removePropertyChangeListener(final PropertyChangeListener listener) {
		getPropertyChange().removePropertyChangeListener(listener);
	}
	
	/**
	 * The firePropertyChange method was generated to support the propertyChange field.
	 */
	public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
		getPropertyChange().firePropertyChange(propertyName, oldValue, newValue);
	}
	
}
